#include <windows.h>

#include "stdclient.h"


#define lpvMessage "hello-message" 

const BYTE	hellomsg[]={"hello"};
const BYTE  byemsg[]={"bye"};




DWORD check_context(ST_PIPE_client *stc_context)
{
	if 	( NULL == stc_context   )
	{
		return MSG_CLIENT_INVALID_PARAM;
	}
	
	if (INVALID_HANDLE_VALUE == stc_context->hPipe   || NULL == stc_context->hPipe ) 
	{
		return MSG_CLIENT_INVALID_HANDLE;
	}

	if (sizeof(ST_PIPE_client) != stc_context->dwsize )
	{
		return MSG_CLIENT_API_LIBVERSION;
	}

	return MSG_CLIENT_SUCCESS;

}
	

DWORD WINAPI msgclient_open(ST_PIPE_client *stc_context,UINT nSize)
{
	//HANDLE	hPipe = NULL   ; 
	BOOL	bFindPipeFlag = 0;
	DWORD	dwMode = 0 ;
	BOOL	fSuccess = 0 ;

	DWORD	cbWritten,cbRead = 0 ;

	BYTE	chBuf[512] = { 0 } ;
	
	
	
	if ( NULL == stc_context  || nSize != sizeof(ST_PIPE_client))
	{
		return MSG_CLIENT_INVALID_PARAM;
	}

	
	bFindPipeFlag = TRUE;

	while (bFindPipeFlag)
	{
		stc_context->hPipe = CreateFileW( 
			dflpszPipename,   // pipe name 
			GENERIC_READ |  // read and write access 
			GENERIC_WRITE, 
			0,              // no sharing 
			NULL,           // no security attributes
			OPEN_EXISTING,  // opens existing pipe 
			0,              // default attributes 
			NULL);          // no template file 

		if (stc_context->hPipe != INVALID_HANDLE_VALUE) 
		{
			//Get Pipe
			break; 
		}

		// Exit if an error other than ERROR_PIPE_BUSY occurs. 

		if (GetLastError() != ERROR_PIPE_BUSY) 
		{
			//MyErrExit("Could not open pipe"); 
			return MSG_C_Could_not_open_pipe;
		}

		// All pipe instances are busy, so wait for 20 seconds. 

		if (! WaitNamedPipeW(dflpszPipename, 20000) ) 
		{
			//MyErrExit("Could not open pipe"); 
			return MSG_C_Could_not_open_pipe;
		}
	} 
	
	

	// The pipe connected; change to message-read mode. 

	dwMode = PIPE_READMODE_MESSAGE; 
	fSuccess = SetNamedPipeHandleState( 
		stc_context->hPipe,    // pipe handle 
		&dwMode,  // new pipe mode 
		NULL,     // don't set maximum bytes 
		NULL);    // don't set maximum time 

	if (!fSuccess) 
	{
		//MyErrExit("SetNamedPipeHandleState"); 
		return MSG_C_SetNamedPipeHandleState;
	}

	// Send a message to the pipe server. 

	

	fSuccess = WriteFile( 
		stc_context->hPipe,     // pipe handle 
		hellomsg,				// message 
		sizeof(hellomsg),		// message length 
		&cbWritten,             // bytes written 
		NULL);                  // not overlapped 
	
	if (! fSuccess) 
	{
		//MyErrExit("WriteFile");
		return MSG_C_WriteFile2PIPE;
	}

	
	// Read from the pipe. 
		
	fSuccess = ReadFile( 
			stc_context->hPipe,    // pipe handle 
			chBuf,    // buffer to receive reply 
			sizeof(chBuf),      // size of buffer 
			&cbRead,  // number of bytes read 
			NULL);    // not overlapped 

	if (! fSuccess && GetLastError() != ERROR_MORE_DATA) 
	{	
		return 1;
		//break; 
	}


	if ( chBuf[0] == 'O' && chBuf[1] == 'K' ) //OK\0\0
	{
		memcpy(&stc_context->auth_token.bContext[0],&chBuf[4],sizeof(ST_AUTH_TOKEN));
				
	}	
	else
	{
		return MSG_C_OPEN_NOTOK;
	}


	
	//CloseHandle(hPipe); 

	return MSG_CLIENT_SUCCESS;
}


DWORD WINAPI msgclient_close(ST_PIPE_client *stc_context)
{	
	DWORD	cbWritten = 0 ;
	BOOL	fSuccess =	FALSE ;
	
	DWORD	dwretval = 0 ;

	dwretval = check_context(stc_context);
	if ( MSG_CLIENT_SUCCESS != dwretval )
	{
		return dwretval;
	}
	
	fSuccess = WriteFile(stc_context->hPipe, byemsg, sizeof(byemsg),&cbWritten, NULL);

	if ( FALSE == fSuccess)
	{
		return MSG_C_WriteFile2PIPE;
		//break; MSG_C_WriteFile2PIPE
	}

	CloseHandle(stc_context->hPipe);
	

	memset(stc_context,0,stc_context->dwsize);

	stc_context->dwclientID = 0 ;

	stc_context->hPipe = NULL ;
	
	return	MSG_CLIENT_SUCCESS  ;
	
}


DWORD WINAPI msgclient_pipe
(
IN ST_PIPE_client *stc_context,
IN void *psend,size_t nsize_send,
OUT void *previce,size_t nsize_revice,unsigned int *lpnretsize
)
{	
	BOOL	fSuccess =FALSE ;
	DWORD	cbWritten = 0;
	DWORD	cbRead = 0 ;
	DWORD	dwretval = 0 ;
	DWORD	dwLasterror=0;


	BYTE	bSendBuf[PIPE_MAXSIZE] = { 0 };
	UINT	bSend = 0 ;

	BYTE	bReviceBuf[PIPE_MAXSIZE] = { 0 };

	BYTE	bParserBuf[PIPE_MAXSIZE] = { 0 };
	UINT	cbParsered = 0 ;

	dwretval = check_context(stc_context);
	if (MSG_CLIENT_SUCCESS != dwretval )
	{
		return dwretval;
	}

	//fSuccess = WriteFile(stc_context->hPipe, byemsg, sizeof(byemsg),&cbWritten, NULL);

	bSend = build_sendrequest(&stc_context->auth_token,psend,nsize_send,bSendBuf,sizeof(bSendBuf));

	fSuccess = WriteFile( 
		stc_context->hPipe,     // pipe handle 
		bSendBuf,				// message 
		bSend,					// message length 
		&cbWritten,             // bytes written 
		NULL);                  // not overlapped 
	
	if (! fSuccess) 
	{
		dwLasterror = GetLastError();
		if ( 233 == dwLasterror  )
		{
			return MSG_SERVER_NO_THREAD ;
		}
		//MyErrExit("WriteFile");
		return MSG_C_WriteFile2PIPE;
	}

	if (cbWritten != bSend )
	{
		return MSG_C_WritePipeSize;
	}

	
	
	
	
	// Read from the pipe. 
	
	fSuccess = ReadFile( 
		stc_context->hPipe,		// pipe handle 
		bReviceBuf,				// buffer to receive reply 
		sizeof(bReviceBuf),			// size of buffer 
		&cbRead,				// number of bytes read 
		NULL);					// not overlapped 
	
	if (! fSuccess && ERROR_MORE_DATA != GetLastError() ) 
	{	
		return MSG_CLIENT_ERROR4;
		//break; 
	}

	if (! paser_sendrequest(&bReviceBuf[0],cbRead,&bParserBuf[0],sizeof(bParserBuf),&cbParsered))
	{
		return MSG_C_AUTH_FAILED;
	}
	
		
	memcpy(previce,bParserBuf,min(cbParsered,nsize_revice));

	if (NULL != lpnretsize)
	{
		*lpnretsize = cbParsered ;
	}

	return MSG_CLIENT_SUCCESS;
}



